package com.xunmall.account.service.impl;

import com.xunmall.account.dto.CompanyDto;
import com.xunmall.account.dto.ManageListDto;
import com.xunmall.account.entity.UserDO;
import com.xunmall.account.mapper.UserMapper;
import com.xunmall.account.service.UserRoleService;
import com.xunmall.account.service.UserService;
import com.xunmall.base.exception.BadRequestException;
import com.xunmall.base.util.StringUtils;
import com.xunmall.base.util.encode.EncodeUtils;
import com.xunmall.base.util.security.DigestUtils;
import com.xunmall.security.password.ShaPasswordEncoder;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * @Author: WangYanjing
 * @Date: 2018/12/27 10:53
 * @Description:
 */
@Service
public class UserServiceImpl implements UserService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    UserRoleService userRoleService;

    @Override
    public Boolean checkUserName(String userName) {
        UserDO userDO = new UserDO();
        userDO.setMobile(userName);
        List<UserDO> userDOS = userMapper.select(userDO);
        if (userDOS.size() > 0) {
            return false;
        } else {
            return true;
        }
    }

    @Override
    public UserDO create(UserDO userDO) {
        if (userDO == null || StringUtils.isBlank(userDO.getMobile()) || StringUtils.isBlank(userDO.getPassword())) {
            throw new BadRequestException("error.account.0001", this);
        }
        // 校验是否重复
        boolean isUnique = checkUserName(userDO.getMobile());
        if (!isUnique) {
            throw new BadRequestException("error.account.0007", this);
        }
        // 密码加密
        byte[] salt = DigestUtils.generateSalt(ShaPasswordEncoder.SALT_SIZE);
        SimpleHash hash = new SimpleHash(ShaPasswordEncoder.HASH_ALGORITHM, userDO.getPassword(),
                org.apache.shiro.util.ByteSource.Util.bytes(salt), ShaPasswordEncoder.HASH_INTERATIONS);
        // 赋值
        userDO.setPassword(hash.toHex());
        userDO.setSalt(EncodeUtils.hexEncode(salt));
        userDO.setStatus(true);
        userDO.buildForInsert();
        int result = userMapper.insertSelective(userDO);
        if (result > 0) {
            return userMapper.selectByPrimaryKey(userDO.getUuid());
        } else {
            throw new BadRequestException("error.account.0002", this);
        }
    }

    @Override
    public UserDO update(UserDO userDO) {
        if (userDO == null || StringUtils.isBlank(userDO.getUuid())) {
            throw new BadRequestException("error.account.0001", this);
        }
        UserDO u = userMapper.selectByPrimaryKey(userDO.getUuid());
        if (u == null) {
            throw new BadRequestException("error.account.0003", this);
        }
        String[] ignoreProperties = new String[]{
                "mobile",
                "password",
                "salt"
        };
        BeanUtils.copyProperties(userDO, u, ignoreProperties);
        u.buildForUpdate();
        int result = userMapper.updateByPrimaryKeySelective(u);
        if (result > 0) {
            return userMapper.selectByPrimaryKey(userDO.getUuid());
        } else {
            throw new BadRequestException("error.account.0002", this);
        }
    }

    @Override
    public Integer forgetPwd(String mobile, String password) {
        if (StringUtils.isBlank(mobile) || StringUtils.isBlank(password)) {
            throw new BadRequestException("error.account.0001", this);
        }
        UserDO userDO = new UserDO();
        userDO.setMobile(mobile);
        userDO = userMapper.selectOne(userDO);
        if (userDO == null) {
            throw new BadRequestException("error.account.0003", this);
        } else {
            // 密码加密
            SimpleHash hash = new SimpleHash(ShaPasswordEncoder.HASH_ALGORITHM, password,
                    ByteSource.Util.bytes(EncodeUtils.hexDecode(userDO.getSalt())), ShaPasswordEncoder.HASH_INTERATIONS);
            userDO.setPassword(hash.toHex());
            userDO.buildForUpdate();
            return userMapper.updateByPrimaryKeySelective(userDO);
        }
    }

    @Override
    public Integer resetPwd(String uuid, String curPassword, String newPassword) {
        if (StringUtils.isBlank(uuid) || StringUtils.isBlank(curPassword) || StringUtils.isBlank(newPassword)) {
            throw new BadRequestException("error.account.0001", this);
        }
        UserDO u = userMapper.selectByPrimaryKey(uuid);
        if (u == null) {
            throw new BadRequestException("error.account.0003", this);
        }
        SimpleHash hashCur = new SimpleHash(ShaPasswordEncoder.HASH_ALGORITHM, curPassword,
                ByteSource.Util.bytes(EncodeUtils.hexDecode(u.getSalt())), ShaPasswordEncoder.HASH_INTERATIONS);
        if (!hashCur.toHex().equals(u.getPassword())) {
            throw new BadRequestException("error.account.0005", this);
        }
        SimpleHash hashNew = new SimpleHash(ShaPasswordEncoder.HASH_ALGORITHM, newPassword,
                ByteSource.Util.bytes(EncodeUtils.hexDecode(u.getSalt())), ShaPasswordEncoder.HASH_INTERATIONS);
        // 赋值
        u.setPassword(hashNew.toHex());
        u.buildForUpdate();
        return userMapper.updateByPrimaryKeySelective(u);
    }

    @Override
    public Integer updateMobile(String uuid, String mobile, String password) {
        if (StringUtils.isBlank(uuid) || StringUtils.isBlank(password)) {
            throw new BadRequestException("error.account.0001", this);
        }
        UserDO u = userMapper.selectByPrimaryKey(uuid);
        if (u == null) {
            throw new BadRequestException("error.account.0003", this);
        }
        SimpleHash hash = new SimpleHash(ShaPasswordEncoder.HASH_ALGORITHM, password,
                ByteSource.Util.bytes(EncodeUtils.hexDecode(u.getSalt())), ShaPasswordEncoder.HASH_INTERATIONS);
        if (!hash.toHex().equals(u.getPassword())) {
            throw new BadRequestException("error.account.0005", this);
        }

        boolean isUnique = checkUserName(mobile);
        if (!isUnique) {
            throw new BadRequestException("error.account.0007", this);
        }
        u.setMobile(mobile);
        u.buildForUpdate();
        return userMapper.updateByPrimaryKeySelective(u);
    }

    @Override
    public UserDO getByUserName(String userName) {
        UserDO userDO = new UserDO();
        userDO.setMobile(userName);
        userDO = userMapper.selectOne(userDO);

        return userDO;
    }

    @Override
    public CompanyDto getUserCompany(String userUuid) {
        return userMapper.getUserCompanies(userUuid);
    }

    @Override
    public Boolean isUserInComp(String userUuid, String companyUuid) {
        return userMapper.isUserInComp(userUuid, companyUuid);
    }

    @Override
    public List<ManageListDto> queryCompManageList(String compUuid) {
        return userRoleService.selectCompManageList(compUuid);
    }

    @Override
    public Integer modifyComp(String uuid, String compUuid, boolean isAppLogin) {
        return userMapper.modifyComp(uuid, compUuid, isAppLogin);
    }

    @Override
    public Boolean checkPwd(String uuid, String password) {
        boolean flag = false;
        if (StringUtils.isBlank(uuid) || StringUtils.isBlank(password)) {
            throw new BadRequestException("error.account.0001", this);
        }
        UserDO u = userMapper.selectByPrimaryKey(uuid);
        if (u == null) {
            throw new BadRequestException("error.account.0003", this);
        }
        SimpleHash hashCur = new SimpleHash(ShaPasswordEncoder.HASH_ALGORITHM, password,
                ByteSource.Util.bytes(EncodeUtils.hexDecode(u.getSalt())), ShaPasswordEncoder.HASH_INTERATIONS);
        if (hashCur.toHex().equals(u.getPassword())) {
            flag = true;
        }
        return flag;
    }

    @Override
    public UserDO getByUuid(String uuid) {
        return userMapper.selectByPrimaryKey(uuid);
    }

}